// 8位宽字符
#define PCRE2_CODE_UNIT_WIDTH 8

#include<stdio.h>
#include<string.h>
#include<pcre2.h>

// 宏定义
#define MAXNUM 1000

 // 查找亲近同学
int find_closest_classmate(int *, int, const char *, const char *);
void output(int *, int); // 输出结果

// 测试
int main()
{
    // 声明变量
    int mno;
    char like[27]; // 26个大写字符+'\0'
    char classmate[MAXNUM + 1];  // MAXNUM个同学+'\0'
    int sno[MAXNUM];

    mno = 1;
    strcpy(like, "ABC");
    strcpy(classmate, "BPTYHJKAMNBPHC");

    // 处理数据
    int n = find_closest_classmate(sno, mno, like, classmate);

    // 输出结果
    output(sno, n);

    return 0;
}

// 查找亲近同学
int find_closest_classmate(int *sno, int myno,
                           const char *like,
                           const char *classmate)
{
    int n = 0;
    size_t offset;

    // 正则处理相关变量
    pcre2_code *re;
    int rc;
    int errornumber;
    PCRE2_SIZE erroroffset;
    pcre2_match_data *match_data;
    PCRE2_SPTR pattern;
    PCRE2_SPTR subject;
    PCRE2_SPTR p_str;
    PCRE2_SIZE *ovector;

    // 构造正则表达式
    char *pat = (char*)malloc((strlen(like) + 2 + 1) * sizeof(char));
    if(pat == NULL)
    {
        printf("not enough memory!\n");
        exit(EXIT_FAILURE);
    }

    memset(pat, 0, (strlen(like) + 2 + 1) * sizeof(char));
    pat[0] = '[';
    strcat(pat, like);
    strcat(pat, "]");

    // 正则表达式(注意用\\转义)
    pattern = (PCRE2_SPTR)pat;
    subject = (PCRE2_SPTR)classmate;

    // 编译正则表达式
    re = pcre2_compile(pattern,               /* 模式(正则表达式) */
                       PCRE2_ZERO_TERMINATED, /* 模式长度('\0'终止字符串) */
                       0,                     /* 默认选项 */
                       &errornumber,          /* 错误编码 */
                       &erroroffset,          /* 错误信息偏移量 */
                       NULL);                 /* 上下文，一般取NULL */
    /* 编译失败处理. */
    if (re == NULL)
    {
        PCRE2_UCHAR buffer[256];
        pcre2_get_error_message(errornumber, buffer, sizeof(buffer));
        printf("PCRE2 compilation failed at offset %d: %s\n",
               (int)erroroffset, buffer);
        exit(EXIT_FAILURE);
    }

    // 构造匹配寄存器以记录匹配结果
    match_data = pcre2_match_data_create_from_pattern(re, NULL);

    // 字符串起始匹配偏移量
    offset = 0;
    do
    {
        // 正则表达式匹配的起始地址
        p_str = subject + offset;

        rc = pcre2_match(re, p_str, PCRE2_ZERO_TERMINATED,
                         0, 0, match_data, NULL);

        // 获取匹配寄存器
        ovector = pcre2_get_ovector_pointer(match_data);

        // 依次判断匹配情况
        if(rc < 0)
        {
            /** 没有找到匹配，结束循环 */
            break;
        }
        else
        {
            // 只记录与自己学号不同的朋友(地址相减)
            if(((const char*)p_str + ovector[0] - classmate + 1) != myno)
            {
                sno[n] = (const char*)p_str + ovector[0] - classmate + 1;
                n++;
            }

            // 偏移量
            offset += ovector[1];
            continue;
        }
    }while(1);

    // 释放内存
    pcre2_match_data_free(match_data);
    pcre2_code_free(re);
    free(pat);

    return n; // 返回找到的亲近同学总数
}

// 输出结果
void output(int *sno, int n)
{
    int i;

    if(n > 0)
    {
        for(i = 0; i < n - 1; i++)
        {
            printf("%d ", sno[i]);
        }
        printf("%d\n", sno[i]); // 避免最后输出多1个空格
    }
    else
    {
        printf("Lonely Xiao Ming\n");
    }
}
